package com.sskj.lib.http;

import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.MutableLiveData;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.annotations.SerializedName;
import com.lzy.okgo.callback.AbsCallback;
import com.lzy.okgo.model.Response;
import com.lzy.okgo.request.base.Request;
import com.sskj.common.util.GSonUtil;
import com.sskj.lib.BaseHttpConfig;
import com.sskj.lib.box.exception.JsonParseException;
import com.sskj.lib.box.exception.LogoutException;
import com.sskj.lib.box.exception.ToastException;
import com.sskj.lib.util.ExceptionUtil;

import org.json.JSONObject;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import okhttp3.ResponseBody;

public abstract class CallBackOption<T> extends AbsCallback<T> {
    enum Strategy {
        LOAD_BIND,//显示加载框和界面生命周期绑定
        UNLOAD_BIND,//不显示加载框和界面生命周期绑定
        UNLOAD_UNBIND//不显示加载框不和界面生命周期绑定
    }

    private ILoadBind<T> iLoadBind;

    public CallBackOption<T> execute(ILoadBind<T> t) {
        iLoadBind = t;
        return this;
    }

    private IBaseViewLife iBaseViewLife;
    private LifecycleOwner lifecycleOwner;
    private Strategy strategy;
    private MutableLiveData<T> tMutableLiveData;

    public CallBackOption() {
    }

    /**
     * 显示加载框和界面生命周期绑定
     */
    public CallBackOption<T> loadBind(IBaseViewLife iBaseViewLife) {
        this.iBaseViewLife = iBaseViewLife;
        strategy = Strategy.LOAD_BIND;

        return this;
    }

    /**
     * 不显示加载框和界面生命周期绑定
     */
    public CallBackOption<T> unLoadBind(LifecycleOwner lifecycleOwner) {
        this.lifecycleOwner = lifecycleOwner;
        strategy = Strategy.UNLOAD_BIND;

        return this;
    }

    /**
     * 不显示加载框不和界面生命周期绑定
     */
    public CallBackOption<T> unLoadunBind() {
        strategy = Strategy.UNLOAD_UNBIND;

        return this;
    }


    @Override
    public void onStart(Request<T, ? extends Request> request) {
        super.onStart(request);
        if (strategy == Strategy.LOAD_BIND) {
            tMutableLiveData = new MutableLiveData<>();
            tMutableLiveData.observe(iBaseViewLife, t -> iLoadBind.excute(t));
            iBaseViewLife.showLoading();
        } else if (strategy == Strategy.UNLOAD_BIND) {
            tMutableLiveData = new MutableLiveData<>();
            tMutableLiveData.observe(lifecycleOwner, t -> iLoadBind.excute(t));
        }

    }


    @Override
    public void onSuccess(Response<T> response) {
        if (strategy == Strategy.UNLOAD_UNBIND) {
            iLoadBind.excute(response.body());
        } else {
            tMutableLiveData.postValue(response.body());
        }
    }

    @Override
    public void onFinish() {
        super.onFinish();
        if (strategy == Strategy.LOAD_BIND) {
            iBaseViewLife.hideLoading();
        }
    }


    @Override
    public T convertResponse(okhttp3.Response response) throws Exception {
        ResponseBody body = response.body();
        if (body == null) return null;
        T data;
        String jsonBody = body.string();
        jsonBody = jsonBody.replace("\"data\":\"\"}", "\"data\":null}");
        JsonBean jsonBean = new Gson().fromJson(jsonBody, JsonBean.class);
        int code = jsonBean.getCode();
        String msg = jsonBean.getMsg();

        if (code == 401 || code == 505) {
            throw new LogoutException(msg);
        } else if (code != BaseHttpConfig.OK) {
            throw new ToastException(msg);
        }
        try {
            Gson gson = GSonUtil.gson;
            Type genericSuperclass = getClass().getGenericSuperclass();
            Type type = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
            data = gson.fromJson(jsonBody, type);
        } catch (JsonSyntaxException e) {
            throw new JsonParseException(response.request().url().url().toString());
        }
        return data;
    }


    @Override
    public void onError(Response<T> response) {
        super.onError(response);
        if (strategy == Strategy.LOAD_BIND) {
            iBaseViewLife.hideLoading();
        }
        ExceptionUtil.dealException(response.getException());
    }

    public class JsonBean {
        @SerializedName(value = "code", alternate = {"status"})
        private int code;
        @SerializedName(value = "msg", alternate = {"message"})
        private String msg;

        public int getCode() {
            return code;
        }

        public void setCode(int code) {
            this.code = code;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }
    }
}
